﻿using System;

using FoosballEye.Model;
using FoosballEye.Repository;
using System.Transactions;

namespace FoosballEye.BLL
{
    using FoosballEye.BLL.Configuration;
    using FoosballEye.Model.Adapters;
    using FoosballEye.BLL.Services;

    public class GameLogic
    {
        private const string Hawkeyeww = "HAWKEYEWW\\";
        private const string HawkeyewwDomain = "@hawkeyeww.com";  
 
        public static NewGame GetNewGame()
        {
            return new NewGame { Players = new PlayerRepository().GetAllPlayers() };
        }

        public static BestPlayers GetBestPlayers()
        {
            return new BestPlayers { Players = new PlayerRepository().GetBestPlayers(ConfigWrapper.CurrentSeasonId) };
        }

        public static BestPlayers GetStatistics()
        {
            return new BestPlayers { Players = new PlayerRepository().GetStatistics(1) };
        }

        public static LastGame GetLastGame()
        {
            Game lastGame = new GameRepository().GetLastGame();
            if (lastGame != null)
            {
                string loser1 = lastGame.WhiteTeamGoals < lastGame.BlackTeamGoals
                    ? lastGame.WhiteTeam.Attacker.Login
                    : lastGame.BlackTeam.Attacker.Login;
                string loser2 = lastGame.WhiteTeamGoals < lastGame.BlackTeamGoals
                    ? lastGame.WhiteTeam.Defender.Login
                    : lastGame.BlackTeam.Defender.Login;
                string winer1 = lastGame.WhiteTeamGoals < lastGame.BlackTeamGoals
                    ? lastGame.BlackTeam.Attacker.Login
                    : lastGame.WhiteTeam.Attacker.Login;
                string winer2 = lastGame.WhiteTeamGoals < lastGame.BlackTeamGoals
                    ? lastGame.BlackTeam.Defender.Login
                    : lastGame.WhiteTeam.Defender.Login;
                return new LastGame
                {
                    InsertDate = lastGame.InsertDate.ToString("M/d/yyyy HH:mm") + " EST",
                    Losers = loser1.Replace(Hawkeyeww, string.Empty) + ", " + loser2.Replace(Hawkeyeww, string.Empty),
                    Winners = winer1.Replace(Hawkeyeww, string.Empty) + ", " + winer2.Replace(Hawkeyeww, string.Empty),
                    Points = lastGame.GamePoints,
                    Result =
                        lastGame.WhiteTeamGoals > lastGame.BlackTeamGoals
                            ? lastGame.WhiteTeamGoals + " : " + lastGame.BlackTeamGoals
                            : lastGame.BlackTeamGoals + " : " + lastGame.WhiteTeamGoals,
                };
            }
            return new LastGame();
        }

        public static Game SaveNewGame(string grayDefence, string grayAttack, string blackDefence, string blackAttack, string grayPoints, string blackPoints, string login, string level)
        {
            login = login.Replace("HAWKEYEWW", string.Empty);

            if(!(new PlayerRepository().GetPlayer(login).IsAdmin |
                grayDefence.Equals(login) |
                grayAttack.Equals(login) |
                blackDefence.Equals(login) |
                blackAttack.Equals(login)))
            {
                throw new BusinessException("You have to be one of players to be able save the match.");
            }
            
            Game game;
            using(TransactionScope ts = new TransactionScope())
            {
                PlayerRepository playerRepository = new PlayerRepository();               

                GameLevel gameLevel = new GameLevelRepository().GetByValue( int.Parse(level) );
                Player grayDefender = playerRepository.GetPlayer(Hawkeyeww + grayDefence);
                Player grayAttacker = playerRepository.GetPlayer(Hawkeyeww + grayAttack);
                Player blackDefender = playerRepository.GetPlayer(Hawkeyeww + blackDefence);
                Player blackAttacker = playerRepository.GetPlayer(Hawkeyeww + blackAttack);
                int grayPoint = int.Parse(grayPoints);
                int blackPoint = int.Parse(blackPoints);
                int wonPoints;

                GameTeam grayTeam = new GameTeam
                {
                    SeasonId = ConfigWrapper.CurrentSeasonId,
                    AttackerId = grayAttacker.Id,
                    DefenderId = grayDefender.Id,
                    InsertDate = DateTime.Now,
                    InsertUser = login
                };
                GameTeam blackTeam = new GameTeam
                {
                    SeasonId = ConfigWrapper.CurrentSeasonId,
                    AttackerId = blackAttacker.Id,
                    DefenderId = blackDefender.Id,
                    InsertDate = DateTime.Now,
                    InsertUser = login
                };

                if (grayPoint > blackPoint)
                {
                    wonPoints = CalculatePoints(grayDefender, grayAttacker, blackDefender, blackAttacker, gameLevel.PercentageValue, grayTeam, blackTeam);
                }
                else if (blackPoint > grayPoint)
                {
                    wonPoints = CalculatePoints(blackDefender, blackAttacker, grayDefender, grayAttacker, gameLevel.PercentageValue, blackTeam, grayTeam);
                }
                else
                {
                    wonPoints = CalculatePointsDraw(blackDefender, blackAttacker, grayDefender, grayAttacker, blackTeam, grayTeam);
                }
                grayDefender.UpdateDate = DateTime.Now;
                grayAttacker.UpdateDate = DateTime.Now;
                blackDefender.UpdateDate = DateTime.Now;
                blackAttacker.UpdateDate = DateTime.Now;
                grayDefender.UpdateUser = login;
                grayAttacker.UpdateUser = login;
                blackDefender.UpdateUser = login;
                blackAttacker.UpdateUser = login;
                playerRepository.DataContext.SaveChanges();
                
                GameTeamRepository gtr = new GameTeamRepository();
                gtr.Insert(grayTeam);
                gtr.Insert(blackTeam);

                game = new Game{
                    SeasonId = ConfigWrapper.CurrentSeasonId,
                    GameLevelId = gameLevel.Id,
                    BlackTeamId = blackTeam.Id,
                    WhiteTeamId = grayTeam.Id,
                    BlackTeamGoals = blackPoint,
                    WhiteTeamGoals = grayPoint,
                    GamePoints = wonPoints,
                    InsertDate = DateTime.Now,
                    InsertUser = login
                };

                GameRepository gr = new GameRepository();
                gr.Insert(game);

                SendMail(blackAttack, blackDefence, grayAttack, grayDefence, blackPoint, grayPoint, wonPoints, game.InsertDate);

                ts.Complete();
            }            

            return game;
        }

        private static void SendMail(string blackAttack, 
                                     string blackDefence, 
                                     string grayAttack, 
                                     string grayDefence, 
                                     int blackPoint, 
                                     int grayPoint, 
                                     int wonPoints, 
                                     DateTime insertDate)
        {
            GameFinishedPlayers gameFinishedPlayers = new GameFinishedPlayers();
            gameFinishedPlayers.BlackAttackerEmail = blackAttack + HawkeyewwDomain;
            gameFinishedPlayers.BlackDefenderEmail = blackDefence + HawkeyewwDomain;
            gameFinishedPlayers.WhiteAttackerEmail = grayAttack + HawkeyewwDomain;
            gameFinishedPlayers.WhiteDefenderEmail = grayDefence + HawkeyewwDomain;
            if (grayPoint > blackPoint)
            {
                gameFinishedPlayers.Winners = grayAttack + ", " + grayDefence;
                gameFinishedPlayers.Losers = blackAttack + ", " + blackDefence;
                gameFinishedPlayers.Result = grayPoint.ToString() + " : " + blackPoint.ToString();
            }
            else
            {
                gameFinishedPlayers.Winners = blackAttack + ", " + blackDefence;
                gameFinishedPlayers.Losers = grayAttack + ", " + grayDefence;
                gameFinishedPlayers.Result = blackPoint.ToString() + " : " + grayPoint.ToString();
            }
            gameFinishedPlayers.WonPoints = wonPoints.ToString();
            gameFinishedPlayers.TimeOfGame = insertDate.ToString("M/d/yyyy HH:mm") + " EST";
            gameFinishedPlayers.EmailTemplatesFolder = System.Web.HttpContext.Current.Server.MapPath("~/EmailTemplates/");
            gameFinishedPlayers.IsDraw = grayPoint == blackPoint;
            gameFinishedPlayers.SesasonId = ConfigWrapper.CurrentSeasonId;
               
            EmailService.SendEmail(gameFinishedPlayers);
        }

        private static int CalculatePoints(
            Player winDefender, 
            Player winAttacker, 
            Player lostDefender, 
            Player lostAttacker, 
            int percentOfPoint, 
            GameTeam winTeam, 
            GameTeam lostTeam)
        {
            lostTeam.DefenderEarnedPoints = CalculatePoints(lostDefender.AccountPoints,percentOfPoint);
            lostTeam.AttackerEarnedPoints = CalculatePoints(lostAttacker.AccountPoints,percentOfPoint);
            lostDefender.AccountPoints += lostTeam.DefenderEarnedPoints;
            lostAttacker.AccountPoints += lostTeam.AttackerEarnedPoints;

            winTeam.DefenderEarnedPoints = -(lostTeam.DefenderEarnedPoints + lostTeam.AttackerEarnedPoints) / 2 + 1;
            winTeam.AttackerEarnedPoints = -(lostTeam.DefenderEarnedPoints + lostTeam.AttackerEarnedPoints) / 2 + 1;
            winDefender.AccountPoints += winTeam.DefenderEarnedPoints;
            winAttacker.AccountPoints += winTeam.AttackerEarnedPoints;

            return winTeam.DefenderEarnedPoints + winTeam.AttackerEarnedPoints;
        }

        private static int CalculatePoints(int points, int percent)
        {
            return (points * percent / 100) == 0  && points > 0 ? -1 : -points * percent / 100;
        }

        private static int CalculatePointsDraw(
            Player winDefender,
            Player winAttacker,
            Player lostDefender,
            Player lostAttacker,
            GameTeam winTeam,
            GameTeam lostTeam)
        {
            winTeam.DefenderEarnedPoints = 1;
            winTeam.AttackerEarnedPoints = 1;
            winDefender.AccountPoints += winTeam.DefenderEarnedPoints;
            winAttacker.AccountPoints += winTeam.AttackerEarnedPoints;

            lostTeam.DefenderEarnedPoints = 1;
            lostTeam.AttackerEarnedPoints = 1;
            lostDefender.AccountPoints += lostTeam.DefenderEarnedPoints;
            lostAttacker.AccountPoints += lostTeam.AttackerEarnedPoints;

            return winTeam.DefenderEarnedPoints + winTeam.AttackerEarnedPoints 
                + lostTeam.DefenderEarnedPoints + lostTeam.AttackerEarnedPoints; 
        }
        
    }
}
